package com.tianquan.miracle.proxy;/**
 * @author starsea
 * @date 2024-10-08 下午12:12
 */


import com.tianquan.miracle.aop.JoinPintImpl;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.List;

/**
 * @BelongsProject: uploaddemo
 * @BelongsPackage: com.tianquan.miracle.proxy
 * @Author: tianquan
 * @CreateTime: 2024-10-08  12:12
 * @Description: cglib代理Aspect
 * @Version: 1.0
 */
public class CglibMethodInvocation implements MethodInterceptor, MethodInvocation {

    // 需要代理的对象
    private Object object;

    private final List<String> objectMethodName;

    // 前置增强方法
    private Method beforeMethod;

    // 后置增强方法
    private Method afterMethod;

    // 用来调用对应方法的类
    private Object target;

    // 环绕通知
    private Method aroundMethod;

    public CglibMethodInvocation(Object object, List<String> objectMethodName, Method beforeMethod,
                                 Method aroundMethod, Method afterMethod, Object target) {
        this.object = object;
        this.objectMethodName = objectMethodName;
        this.beforeMethod = beforeMethod;
        this.aroundMethod = aroundMethod;
        this.afterMethod = afterMethod;
        this.target = target;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        // 如果不是需要代理的方法，则直接调用
        if (!objectMethodName.contains(method.getName())) return method.invoke(this.object, objects);
        if (beforeMethod != null) beforeMethod.invoke(target);
        Object invoke = null;
        // 是否有环绕通知
        if (aroundMethod != null) {
            invoke = aroundMethod.invoke(target, new JoinPintImpl(this.object, method, objects));
        } else {
            // 通过反射调用代理类的方法
            invoke = method.invoke(this.object, objects);
        }
        if (afterMethod != null) invoke = afterMethod.invoke(target);
        return invoke;
    }

    public Object getProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(object.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }


}
